package oa.hleast.xswl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import oa.hleast.common.constant.GlobalConstants;
import oa.hleast.common.result.ResultCode;
import oa.hleast.common.web.exception.BizException;
import oa.hleast.xswl.common.constant.ReviewStatusEnum;
import oa.hleast.xswl.mapper.SysUserMapper;
import oa.hleast.xswl.mapper.store.StoreInfoMapper;
import oa.hleast.xswl.pojo.domain.SysUser;
import oa.hleast.xswl.pojo.domain.SysUserRole;
import oa.hleast.xswl.pojo.domain.store.StoreInfo;
import oa.hleast.xswl.pojo.dto.SysUserDto;
import oa.hleast.xswl.pojo.dto.UserDTO;
import oa.hleast.xswl.pojo.dto.store.StoreInfoDto;
import oa.hleast.xswl.service.ISysUserRoleService;
import oa.hleast.xswl.service.ISysUserService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
@AllArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {


    private final PasswordEncoder passwordEncoder;

    private final ISysUserRoleService iSysUserRoleService;

    private final StoreInfoMapper storeInfoMapper;

    @Override
    public IPage<SysUser> list(Page<SysUser> page, SysUser user) {
        List<SysUser> list = this.baseMapper.list(page, user);
        page.setRecords(list);
        return page;
    }

    @Override
    public boolean saveUser(SysUser user) {
        user.setPassword(passwordEncoder.encode(GlobalConstants.DEFAULT_USER_PASSWORD));
        boolean result = this.save(user);
        if (result) {
            List<Long> roleIds = user.getRoleIds();
            if (CollectionUtil.isNotEmpty(roleIds)) {
                List<SysUserRole> userRoleList = new ArrayList<>();
                roleIds.forEach(roleId -> userRoleList.add(new SysUserRole().setUserId(user.getId()).setRoleId(roleId)));
                result = iSysUserRoleService.saveBatch(userRoleList);
            }
        }
        return result;
    }

    @Override
    public boolean updateUser(SysUser user) {

        List<Long> dbRoleIds = iSysUserRoleService.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, user.getId())).stream().map(item -> item.getRoleId()).collect(Collectors.toList());

        List<Long> roleIds = user.getRoleIds();

        List<Long> addRoleIds = roleIds.stream().filter(roleId -> !dbRoleIds.contains(roleId)).collect(Collectors.toList());
        List<Long> removeRoleIds = dbRoleIds.stream().filter(roleId -> !roleIds.contains(roleId)).collect(Collectors.toList());

        if (CollectionUtil.isNotEmpty(addRoleIds)) {
            List<SysUserRole> addUserRoleList = new ArrayList<>();
            addRoleIds.forEach(roleId -> {
                addUserRoleList.add(new SysUserRole().setUserId(user.getId()).setRoleId(roleId));
            });
            iSysUserRoleService.saveBatch(addUserRoleList);
        }

        if (CollectionUtil.isNotEmpty(removeRoleIds)) {
            removeRoleIds.forEach(roleId -> {
                iSysUserRoleService.remove(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, user.getId()).eq(SysUserRole::getRoleId, roleId));
            });
        }

        boolean result = this.updateById(user);
        return result;
    }

    @Override
    public UserDTO getUserByUsername(String username) {
        SysUser user = this.getOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUsername, username));

        // 用户不存在，返回自定义异常，让调用端处理后续逻辑
        if (user == null) {
            throw new BizException(ResultCode.USER_NOT_EXIST.getMsg());
        }

        // Entity->DTO
        UserDTO userDTO = new UserDTO();
        BeanUtil.copyProperties(user, userDTO);

        // 获取用户的角色ID集合
        List<Long> roleIds = iSysUserRoleService.list(new LambdaQueryWrapper<SysUserRole>()
                .eq(SysUserRole::getUserId, user.getId())
        ).stream().map(item -> item.getRoleId()).collect(Collectors.toList());
        userDTO.setRoleIds(roleIds);
        return userDTO;
    }

    @Override
    public boolean updateStoreInfo(Long id, Long storeId) {
        boolean update = this.update(
                new LambdaUpdateWrapper<SysUser>()
                        .set(SysUser::getHaveStore, true)
                        .set(SysUser::getStoreId, storeId)
                        .eq(SysUser::getId, id)
        );

        log.info("userId = {},storeId = {} ", id, storeId);
        return update;
    }

    @Override
    public SysUserDto getSysUserDtoById(Long userId) {
        SysUser sysUser = this.getById(userId);
        SysUserDto userDto = new SysUserDto();
        BeanUtil.copyProperties(sysUser, userDto);

        Boolean haveStore = sysUser.getHaveStore();
        log.info("haveStore = {},sysUser = {}", haveStore, sysUser);
        if (haveStore) {
            StoreInfoDto storeInfoDto = new StoreInfoDto();
            StoreInfo storeInfo = storeInfoMapper.selectById(sysUser.getStoreId());
            BeanUtil.copyProperties(storeInfo, storeInfoDto);
            userDto.setStoreInfoDto(storeInfoDto);
        }

        log.info("userDto = {}", userDto);
        return userDto;
    }

    /**
     * 检查是否重名
     * sysUser 与 storeInfo 双重检查
     *
     * @param userName 账户名
     */
    @Override
    public boolean checkRepeatUserName(String userName) {
        int count = this.count(new LambdaUpdateWrapper<SysUser>().eq(SysUser::getUsername, userName));
        if (count > 0) {
            throw new BizException("该账户已被占用");
        }
        Integer storeUserInfoCount = storeInfoMapper.selectCount(new LambdaUpdateWrapper<StoreInfo>()
                .eq(StoreInfo::getRegisteredUserName, userName)
                .eq(StoreInfo::getReviewStatus, ReviewStatusEnum.PASS.getCode())
        );
        if (storeUserInfoCount > 0) {
            throw new BizException("该账户已在审核中,请耐心等待");
        }
        return false;
    }
}
